const people = [
  { name: "Alice", age: 30, sex: "female" },
  { name: "Bob", age: 25, sex: "male" },
  { name: "Charlie", age: 35, sex: "male" },
  { name: "David", age: 40, sex: "male" },
  { name: "Emma", age: 28, sex: "female" },
  { name: "Frank", age: 32, sex: "male" },
];

/**
 * 根据提供的生成键的函数或属性名，将数组中的元素分组。
 * @param {Array} arr - 要分组的数组。
 * @param {Function|string} generateKey - 用于生成元素分组键的函数或属性名。
 * 如果是函数，它将接收当前元素、当前索引和原数组作为参数，并应返回一个键。
 * 如果是字符串，则表示原数组元素中的属性名，该属性值将用作键。
 * @returns {Object} - 一个对象，其中键是根据generateKey生成的键，值是包含具有相同键的原数组元素的数组。
 */
function groupBy(arr, generateKey) {
  // 如果generateKey是字符串，则将其转换为一个函数，该函数从元素中获取指定属性名的值作为键
  if (typeof generateKey === "string") {
    const propName = generateKey;
    generateKey = (item) => item[propName];
  }

  // 初始化结果对象
  const result = {};

  // 遍历数组，为每个元素生成一个键，并根据键将其添加到相应的分组中
  for (let i = 0; i < arr.length; i++) {
    const key = generateKey(arr[i], i, arr); // 生成键
    if (result[key]) {
      result[key].push(arr[i]); // 如果键已存在，将元素添加到该键对应的数组中
    } else {
      result[key] = [arr[i]]; // 如果键不存在，创建该键，并将其初始化为包含当前元素的数组
    }
  }
  return result;
}

const result1 = groupBy(people, "sex");

const result2 = groupBy(people, (person) => person.age);
